/**
 * Copyright (c), 上海沃恩信息科技有限公司.
 * All rights reserved.
 * Licensed under BSD (https://www.pittypat.work/bsd.html).
 */

package pittypat.web;

import java.io.IOException;
import java.io.StringWriter;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import pittypat.IAsyncProgress;
import pittypat.IJson;
import pittypat.Json;

/**
 * 向 WebSocket 请求客户端汇报操作进度。
 */
final class WebSocketAsyncProgress implements IAsyncProgress {
	private static final Logger LOGGER = LogManager.getLogger(WebSocketAsyncProgress.class);

	// 目标 WebSocket 连接
	private WebSocket socket;

	/**
	 * 初始化 WebSocketAsyncProgress 的新实例。
	 * 
	 * @param socket
	 *            WebSocket 连接。可以为 null，此时 report 方法什么都不做，也不产生异常。
	 */
	public WebSocketAsyncProgress(WebSocket socket) {
		this.socket = socket;
	}

	/**
	 * 获取基础 WebSocket。可能为 null，此时 report 方法什么都不做，也不产生异常。
	 * 
	 * @return 已经建立的 WebSocket 连接。
	 */
	public WebSocket getWebSocket() {
		return this.socket;
	}

	/**
	 * 汇报操作的进度。
	 * <p>
	 * 如果内部连接为 null，什么都不做，也不产生异常。
	 * 
	 * @param percent
	 *            当前进度的百分比，0-100 之间。
	 * @param message
	 *            当前进度下的消息。
	 * @param value
	 *            同时发送给远程终端的值。
	 */
	@Override
	public void report(float percent, String message, IJson value) {
		if (this.socket == null) {
			return;
		}

		// 确保百分比介于 0 - 100 之间
		percent = percent < 0 ? 0 : (percent > 100 ? 100 : percent);

		message = message == null ? "" : message;
		String json = "";

		if (value == null) {
			// 没有提供值时的 JSON 字符串
			json = "{\"type\":\"progress\",\"percent\":" + percent + ",\"message\":\"" + Json.escape(message)
					+ "\",\"value\":null}";
		} else {
			// 提供值时的 JSON 字符串
			StringWriter writer = new StringWriter(256);
			try {
				writer.write("{\"type\":\"progress\",\"percent\":");
				writer.write(((Float) percent).toString());
				writer.write(",\"message\":\"");
				writer.write(Json.escape(message));
				writer.write("\",\"value\":");
				value.write(writer);
				writer.write(",\"valueType\":\"");
				writer.write(Json.getTypeName(value));
				writer.write("\"}");

				json = writer.toString();
			} catch (IOException e) {
				LOGGER.error(e.getLocalizedMessage(), e);
				// 发生错误时不再发送消息
				return;
			} finally {
				try {
					writer.close();
				} catch (IOException e) {
					LOGGER.error(e.getLocalizedMessage(), e);
				}
			}
		}

		try {
			this.socket.sendAsync(json);
		} catch (IOException e) {
			LOGGER.error(e.getLocalizedMessage(), e);
		}
	}
}
